---
title: "Political Knowledge and Perceptions of Influence in Political Conversation"
subtitle: "Code for Reproducing Main Text and Appendix Results"
author: "Aidan Combs"
date: "11-25-2025"
output: pdf_document
---

This code produces the results, tables, and figures presented in the main text and appendix of the manuscript.

```{r}
library(tidyverse)
library(ggplot2)
library(RColorBrewer)
library(sandwich)
library(lmtest)
library(kableExtra)
library(ordinal)
library(patchwork)
library(broom)

knitr::opts_chunk$set(echo = FALSE, message = FALSE, error = FALSE, tidy.opts = list(width.cutoff = 80), tidy = TRUE)
set.seed(1)
theme_set(theme_minimal())
```

# Setup

## Functions

These functions impute missing political knowledge responses using one of four methods. "Random" is used for results presented in the main text. Other options are compared in the supplementary information.

```{r}
random_knowledge_discussit <- function(data, type = c("drop", "random", "right", "wrong")){
  if(type == "drop"){
    new_data <- data %>% 
      filter(!is.na(know_senator) & !is.na(know_roberts) & !is.na(know_speaker)) %>% 
    mutate(political_knowledge = know_speaker + know_senator + know_roberts,
           political_knowledge_std = (political_knowledge - mean(political_knowledge))/sd(political_knowledge))
  } else {
    prob = case_when(type == "random" ~ .25, 
                     type == "right" ~ 1,
                     type == "wrong" ~ 0)
    new_data <- data
    new_data$know_speaker <- as.integer(data$know_speaker)
    new_data$know_senator <- as.integer(data$know_senator)
    new_data$know_roberts <- as.integer(data$know_roberts)
    new_data$spk_mis <- is.na(new_data$know_speaker)
    new_data$sen_mis <- is.na(new_data$know_senator)
    new_data$rob_mis <- is.na(new_data$know_roberts)
    for(i in 1:nrow(data)){
      if(is.na(new_data[i, 'know_speaker'])){
        new_data[i, 'know_speaker'] <- rbinom(1, 1, prob)
      }
      if(is.na(new_data[i, 'know_senator'])){
        new_data[i, 'know_senator'] <- rbinom(1, 1, prob)
      }
      if(is.na(new_data[i, 'know_roberts'])){
        new_data[i, 'know_roberts'] <- rbinom(1, 1, prob)
      }
    }
    
    new_data <- new_data %>% 
      ungroup() |> 
    mutate(political_knowledge = know_speaker + know_senator + know_roberts,
           political_knowledge_std = (political_knowledge - mean(political_knowledge))/sd(political_knowledge))
  }
  return(as.data.frame(new_data))
}

random_knowledge_unitedem <- function(data, type = c("drop", "random", "right", "wrong")){
  if(type == "drop"){
    new_data <- data %>% 
      mutate(anyNA = !(!is.na(know_roberts) & 
                         !is.na(know_senator) & 
                         !is.na(know_speaker) & 
                         !is.na(know_majority) & 
                         !is.na(know_womenInCongress) & 
                         !is.na(know_supremeCourt))) %>% 
      filter(anyNA == FALSE) %>% 
      rename(know_roberts_fill = know_roberts,
             know_majority_fill = know_majority,
             know_senator_fill = know_senator,
             know_speaker_fill = know_speaker,
             know_womenInCongress_fill = know_womenInCongress,
             know_supremeCourt_fill = know_supremeCourt) %>% 
      mutate(political_knowledge = know_roberts_fill + know_senator_fill + know_supremeCourt_fill + know_speaker_fill + know_womenInCongress_fill + know_majority_fill,
             political_knowledge_std = (political_knowledge - mean(political_knowledge))/sd(political_knowledge))
  } else {
    probs <- case_when(type == "random" ~ c(.25, .5, .25, .33, .25, .2),
                       type == "right" ~ rep(1, 6),
                       type == "wrong" ~ rep(0, 6))
    new_data <- data %>% 
      rowwise() %>% 
      mutate(know_roberts_fill = ifelse(is.na(know_roberts), rbinom(1, 1, probs[1]), know_roberts),
             know_majority_fill = ifelse(is.na(know_majority), rbinom(1, 1, probs[2]), know_majority),
             know_senator_fill = ifelse(is.na(know_senator), rbinom(1, 1, probs[3]), know_senator),
             know_speaker_fill = ifelse(is.na(know_speaker), rbinom(1, 1, probs[4]), know_speaker),
             know_womenInCongress_fill = ifelse(is.na(know_womenInCongress), rbinom(1, 1, probs[5]), know_womenInCongress),
             know_supremeCourt_fill = ifelse(is.na(know_supremeCourt), rbinom(1, 1, probs[6]), know_supremeCourt)) %>% 
      ungroup() %>% 
      mutate(political_knowledge = know_roberts_fill + know_senator_fill + know_supremeCourt_fill + know_speaker_fill + know_womenInCongress_fill + know_majority_fill,
             political_knowledge_std = (political_knowledge - mean(political_knowledge))/sd(political_knowledge))
  }
  return(new_data)
}
```

This is a convenience function for estimating the models and extracting needed information.

```{r}
mod.robust <- function(eq, data, source, knowmis, fam = "gauss"){
  if(source == "dapp"){
    data = data |> 
      filter(analysisgroup_app)
  } else if (source == "dsurvey") {
    data = data |> 
      filter(analysisgroup_survey)
  } else if (source == "urank"){
    data = data |> 
      filter(analysisgroup_rank)
  } else if (source == "utherm"){
    data = data |> 
      filter(analysisgroup_therm)
  }
  
  if(fam == "gauss"){
    mod <- lm(eq, data = data)
  } else if (fam == "ord"){
    mod <- ordinal::clm(eq, data = data)
  }
  
  coefs <- broom::tidy(coeftest(mod, vcov = vcovCL, cluster = data$chatID)) |>
    mutate(source = source,
           n = nobs(mod)) |>
    full_join(
      tibble(
        term = rownames(coefci(mod)),
        lower = coefci(mod, vcov = vcovCL, cluster = data$chatID)[,1],
        upper = coefci(mod, vcov = vcovCL, cluster = data$chatID)[,2],
        knowmis = knowmis)
    )

  return(list(mod, coefs))
}
```

## Load study data and impute missing political knowledge
```{r}
unitedem <- read_csv("unitedem_repcode.csv") |> 
  mutate(
    perc_inf = factor(
      perc_inf,
      levels = c('Disagree very strongly',
                 'Disagree strongly',
                 'Disagree somewhat',
                 'Neither agree nor disagree',
                 'Agree somewhat',
                 'Agree strongly',
                 'Agree very strongly')),
    gender = factor(
      gender, levels = c("Woman", "Man")
    ),
    manipulationCondition = factor(
      manipulationCondition,
      levels = c("opposite_none", "same_none", "opposite_selfmislabel", "opposite_partnermislabel"))
  ) 


discussit <- read_csv("discussit_repcode.csv") |> 
  mutate(
    perc_inf = factor(
      perc_inf,
      levels = c('Disagree very strongly',
                 'Disagree strongly',
                 'Disagree somewhat',
                 'Neither agree nor disagree',
                 'Agree somewhat',
                 'Agree strongly',
                 'Agree very strongly')),
    displayCondition = factor(
      displayCondition, 
      levels = c("none", "correct", "incorrect")
    ),
    topic = factor(
      topic, 
      levels = c("immigration", "gunControl")
    ),
    party = factor(
      party, 
      levels = c("Democrat", "Republican")),
    gender = factor(
      gender, 
      levels = c("Woman", "Man")
    )
  )

u_randassign <- random_knowledge_unitedem(unitedem, type = "random")
d_randassign <- random_knowledge_discussit(discussit, type = "random")
```

# Main text

## Descriptive info 
### N's and drops

```{r}
n_discussit <- d_randassign |> 
  select(analysisgroup_app, analysisgroup_survey, chatID) |> 
  summarize(
    n_app = sum(analysisgroup_app),
    n_survey = sum(analysisgroup_survey),
    n_overlap = sum(analysisgroup_survey & analysisgroup_app),
    total = n()
  )

n_unitedem <- u_randassign |> 
  select(analysisgroup_rank, analysisgroup_therm, chatID) |> 
  summarize(
    n_rank = sum(analysisgroup_rank),
    n_therm = sum(analysisgroup_therm),
    n_overlap = sum(analysisgroup_rank & analysisgroup_therm),
    total = n()
  )

n_discussit
n_unitedem
```

### Relationship between influence and perceived influence

#### Figure 1: influence descriptive plot

##### DiscussIt setup
```{r}
discussit_plot <- discussit |> 
  mutate(
    converge_app = actualinf_app > 0,
    converge_survey = actualinf_survey > 0)

discussit_plotmod_app <- lm(perc_inf_num ~ converge_app, data = discussit_plot)
d_vcov_mat_app <- vcovCL(discussit_plotmod_app, cluster = ~chatID)

discussit_plotmod_survey <- lm(perc_inf_num ~ converge_survey, data = discussit_plot)
d_vcov_mat_survey <- vcovCL(discussit_plotmod_survey, cluster = ~chatID)

discussit_sumstats_app <- prediction::prediction(discussit_plotmod_app, vcov = d_vcov_mat_app) |> 
  group_by(converge_app) |> 
  mutate(n = n()) |> 
  ungroup() |> 
  select(converge_app, fitted, se.fitted, n) |> 
  distinct() |> 
  rename(mean = fitted,
         converge = converge_app) |> 
  mutate(
    lower = mean - qt(.975, df = n-1)*se.fitted,
    upper = mean + qt(.975, df = n-1)*se.fitted,
    source = "app"
    )

discussit_sumstats_survey <- prediction::prediction(discussit_plotmod_survey, vcov = d_vcov_mat_survey) |> 
  group_by(converge_survey) |> 
  mutate(n = n()) |> 
  ungroup() |> 
  select(converge_survey, fitted, se.fitted, n) |> 
  distinct() |> 
  rename(mean = fitted, 
         converge = converge_survey) |> 
  mutate(
    lower = mean - qt(.975, df = n-1)*se.fitted,
    upper = mean + qt(.975, df = n-1)*se.fitted,
    source = "survey"
    )

discussit_sumstats <- discussit_sumstats_app |> 
  full_join(discussit_sumstats_survey)
```

##### UniteDem setup
```{r}
unitedem_plot <- unitedem |> 
  mutate(converge_rank = actualinf_rank > 0,
         converge_therm = actualinf_therm > 0)

unitedem_plotmod_rank <- lm(perc_inf_num ~ converge_rank, data = unitedem_plot)
u_vcov_mat_rank <- vcovCL(unitedem_plotmod_rank, cluster = ~chatID)

unitedem_plotmod_therm <- lm(perc_inf_num ~ converge_therm, data = unitedem_plot)
u_vcov_mat_therm <- vcovCL(unitedem_plotmod_therm, cluster = ~chatID)

unitedem_sumstats_rank <- prediction::prediction(unitedem_plotmod_rank, vcov = u_vcov_mat_rank) |> 
  group_by(converge_rank) |> 
  mutate(n = n()) |> 
  ungroup() |> 
  select(converge_rank, fitted, se.fitted, n) |> 
  distinct() |> 
  rename(mean = fitted,
         converge = converge_rank) |> 
  mutate(
    lower = mean - qt(.975, df = n-1)*se.fitted,
    upper = mean + qt(.975, df = n-1)*se.fitted,
    source = "rank"
    )

unitedem_sumstats_therm <- prediction::prediction(unitedem_plotmod_therm, vcov = u_vcov_mat_therm) |> 
  group_by(converge_therm) |> 
  mutate(n = n()) |> 
  ungroup() |> 
  select(converge_therm, fitted, se.fitted, n) |> 
  distinct() |> 
  rename(mean = fitted, 
         converge = converge_therm) |> 
  mutate(
    lower = mean - qt(.975, df = n-1)*se.fitted,
    upper = mean + qt(.975, df = n-1)*se.fitted,
    source = "therm"
    )

unitedem_sumstats <- unitedem_sumstats_rank |> 
  full_join(unitedem_sumstats_therm)
```

##### Plot creation
```{r}
combined_plot <- select(discussit_plot, converge_app, converge_survey, perc_inf_num, perc_inf) |> 
  mutate(data = "DiscussIt") |> 
  full_join(mutate(select(unitedem_plot, converge_rank, converge_therm, perc_inf_num, perc_inf), data = "UniteDem")) |> 
  pivot_longer(cols = starts_with("converge"), names_to = "source", names_prefix = "converge_", values_to = "converge") |> 
  filter(!is.na(converge)) |> 
  mutate(converge = ifelse(converge, "True", "False"),
         source = case_when(source == "rank" ~ "UniteDem\nRank",
                            source == "therm" ~ "UniteDem\nThermometer",
                            source == "app" ~ "DiscussIt\nApp",
                            source == "survey" ~ "DiscussIt\nSurveys"))

combined_sumstats <- select(discussit_sumstats, mean, lower, upper, converge, source) |> 
  mutate(data = "DiscussIt") |> 
  full_join(mutate(select(unitedem_sumstats, mean, lower, upper, converge, source), data = "UniteDem")) |> 
  mutate(converge = ifelse(converge, "True", "False"),
         source = case_when(source == "rank" ~ "UniteDem\nRank",
                            source == "therm" ~ "UniteDem\nThermometer",
                            source == "app" ~ "DiscussIt\nApp",
                            source == "survey" ~ "DiscussIt\nSurveys"))

plot_both <- ggplot(combined_plot, aes(x = converge, y = perc_inf_num, fill = converge, color = converge))  +
  geom_jitter(
    aes(y = perc_inf),
    width = .1,
    size = .01) + 
  ggdist::stat_halfeye(
    adjust = 1.5,
    .width = 0,
    point_color = NA,
    density = "bounded",
    justification = -.4,
    alpha = .5,
    width = .7
  ) + 
  geom_errorbar(data = combined_sumstats, 
                inherit.aes = FALSE, 
                width = .4,
                linewidth = .5,
                aes(ymin = lower, ymax = upper, x = converge)) + 
  geom_point(data = combined_sumstats, 
             inherit.aes = FALSE,
             size = 2,
             aes(x = converge, y = mean)) + 
  facet_wrap(facets = "source", nrow = 1) +
  theme(legend.position = "none",
        text = element_text(family = "serif", size = 12)) + 
  labs(
    x = "Influence: Partner's opinion moved toward R's initial opinion",
    y = "Perceived influence: R's agreement with\n'I influenced my discussion partner'"
  )

plot_both

ggsave("figs_submit/f1_influencedesc.png", plot_both, width = 6, height = 3.5)
```

#### T tests on differences

```{r}
ttest_stats <- discussit_sumstats |> 
  full_join(unitedem_sumstats) |> 
  select(-lower, -upper) |> 
  mutate(var = se.fitted*se.fitted*n) |> 
  pivot_wider(names_from = converge, values_from = c("mean", "se.fitted", "n", "var")) |> 
  mutate(
    se_pool = sqrt(se.fitted_TRUE/sqrt(n_TRUE) + se.fitted_FALSE/sqrt(n_FALSE)),
    t = abs((mean_TRUE - mean_FALSE)/se_pool),
    # Welch-Satterthwaite equation for df calculation
    df = (var_TRUE/n_TRUE + var_FALSE/n_FALSE)^2/((var_TRUE/n_TRUE)^2/(n_TRUE-1) + (var_FALSE/n_FALSE)^2/(n_FALSE-1)),
    p_df = pt(t, df = df, lower.tail = FALSE)*2,
    # for comparison: z distribution
    p_inf = pt(t, df = Inf, lower.tail = FALSE)*2
  )

#ttest_stats
```

## Models
### Figure 2: effect of political knowledge on perceived influence

```{r}
percinf.dapp <- mod.robust(eq = "perc_inf ~ political_knowledge_std + actualinf_app_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                           data = d_randassign, source = "dapp", knowmis = "randassign", fam = "ord")
mpercinf.dapp <- percinf.dapp[[1]]
coefs.percinf.dapp <- percinf.dapp[[2]]

percinf.dsurvey <-mod.robust(eq = "perc_inf ~ political_knowledge_std + actualinf_survey_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_randassign, source = "dsurvey", knowmis = "randassign", fam = "ord")
mpercinf.dsurvey <- percinf.dsurvey[[1]]
coefs.percinf.dsurvey <- percinf.dsurvey[[2]]

percinf.urank <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_rank_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition",
                      data = u_randassign, source = "urank", knowmis = "randassign", fam = "ord")
mpercinf.urank <- percinf.urank[[1]]
coefs.percinf.urank <- percinf.urank[[2]]

percinf.utherm <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_therm_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition",
                      data = u_randassign, source = "utherm", knowmis = "randassign", fam = "ord")
mpercinf.utherm <- percinf.utherm[[1]]
coefs.percinf.utherm <- percinf.utherm[[2]]

coefs.percinf <- coefs.percinf.dapp |> 
  full_join(coefs.percinf.dsurvey) |> 
  full_join(coefs.percinf.urank) |> 
  full_join(coefs.percinf.utherm) |> 
  filter(str_detect(term, "knowledge|ideology|actualinf|MyRank1")) |> 
  mutate(
    data = ifelse(str_detect(source, "^d"), "DiscussIt", "UniteDem"),
    dispterm = case_when(
      str_detect(term, "actualinf|MyRank1") ~ "Influence",
      term == "ideology" ~ "Ideology (linear)",
      term == "ideologyabs" ~ "Ideology (absolute val)",
      # term == "ideology2" ~ "Ideology (squared)",
      term == "political_knowledge_std" ~ "Political knowledge"),
    dispterm = factor(dispterm, levels = c("Influence", "Political knowledge", "Ideology (linear)", "Ideology (squared)", "Ideology (absolute val)"), ordered = TRUE)
  )

ggplot(coefs.percinf, aes(y = dispterm, x = exp(estimate), xmin = exp(lower), xmax = exp(upper), color = source, shape = source)) +
  geom_vline(xintercept = 1, alpha = .5) +
  geom_pointrange(position = position_dodge2(width = .3)) + 
  scale_y_discrete(limits = rev) +
  scale_color_manual(
    breaks = c(
      "dsurvey", 
      "dapp",
      "urank", 
      "utherm"
    ),
    values = c(
    "dsurvey" = "dodgerblue3", 
    "dapp" = "lightskyblue", 
    "urank" = "firebrick3", 
    "utherm" = "palevioletred1"),
    labels = c(
      "DiscussIt: Surveys",
      "DiscussIt: App",
      "UniteDem: Rank", 
      "UniteDem: Thermometer"
    )) +
  scale_shape_manual(
    breaks = c(
      "dsurvey", 
      "dapp",
      "urank", 
      "utherm"
    ),
    values = c(
    "dsurvey" = 17, 
    "dapp" = 17, 
    "urank" = 19, 
    "utherm" = 19),
    labels = c(
      "DiscussIt: Surveys",
      "DiscussIt: App",
      "UniteDem: Rank", 
      "UniteDem: Thermometer"
    )) +
  labs(y = "",
       x = "Estimated effects on perceived influence (exponentiated log odds units)",
       color = "Influence measurement",
       shape = "Influence measurement") + 
  theme(text = element_text(size = 12, family = "serif"))

ggsave("figs_submit/f2_percinfeffects.png", width = 6, height = 3)
```

### Figure 3: effect of political knowledge on actual influence

```{r}
inf.dapp <- mod.robust(eq = "actualinf_app_std ~ political_knowledge_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_randassign, source = "dapp", knowmis = "randassign")
minf.dapp <- lm("actualinf_app_std ~ political_knowledge_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_randassign)
coefs.inf.dapp <- inf.dapp[[2]]

inf.dsurvey <- mod.robust("actualinf_survey_std ~ political_knowledge_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_randassign, source = "dsurvey", knowmis = "randassign")
minf.dsurvey <- lm("actualinf_survey_std ~ political_knowledge_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_randassign)
coefs.inf.dsurvey <- inf.dsurvey[[2]]

inf.urank <- mod.robust(eq = "actualinf_rank_std ~ political_knowledge_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition", data = u_randassign, source = "urank", knowmis = "randassign")
minf.urank <- lm("actualinf_rank_std ~ political_knowledge_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition", data = u_randassign)
coefs.inf.urank <- inf.urank[[2]]

inf.utherm <- mod.robust(eq = "actualinf_therm_std ~ political_knowledge_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition", data = u_randassign, source = "utherm", knowmis = "randassign")
minf.utherm <- lm("actualinf_therm_std ~ political_knowledge_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition", data = u_randassign)
coefs.inf.utherm <- inf.utherm[[2]]

coefs.inf <- coefs.inf.dapp |> 
  full_join(coefs.inf.dsurvey) |> 
  full_join(coefs.inf.urank) |> 
  full_join(coefs.inf.utherm) |> 
  filter(str_detect(term, "knowledge")) |> 
  arrange(estimate)

ggplot(coefs.inf, aes(y = source, x = estimate, xmin = lower, xmax = upper)) +
  geom_vline(xintercept = 0, alpha = .5) +
  geom_pointrange() + 
  scale_y_discrete(
    breaks = c("dapp",
               "dsurvey",
               "urank",
               "utherm"),
    labels = c("DiscussIt: App",
               "DiscussIt: Survey",
               "UniteDem: Rank",
               "UniteDem: Thermometer")
  ) +
  labs(y = "",
       x = "Estimated effect of political knowledge on influence") + 
  theme(text = element_text(size = 12, family = "serif"))

ggsave("figs_submit/f3_infeffects.png", width = 6, height = 3)
```

### Figure 4: mediation model coefficients

```{r}
d.mediation.app <- d_randassign |> 
  filter(analysisgroup_app)
d.mediation.survey <- d_randassign |> 
  filter(analysisgroup_survey)
u.mediation.rank <- u_randassign |> 
  filter(analysisgroup_rank)
u.mediation.therm <- u_randassign |> 
  filter(analysisgroup_therm)

med.dapp <- lm("perc_inf_num ~ political_knowledge_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", 
                         data = d.mediation.app)
med.dsurvey <- lm("perc_inf_num ~ political_knowledge_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", 
                            data = d.mediation.survey)
med.urank <- lm("perc_inf_num ~ political_knowledge_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition", 
                          data = u.mediation.rank)
med.utherm <- lm("perc_inf_num ~ political_knowledge_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition", 
                           data = u.mediation.therm)

out.dapp <- lm("actualinf_app_std ~ perc_inf_num + political_knowledge_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", 
               data = d.mediation.app)
out.dsurvey <- lm("actualinf_survey_std ~ perc_inf_num + political_knowledge_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", 
               data = d.mediation.survey)
out.urank <- lm("actualinf_rank_std ~ perc_inf_num + political_knowledge_std + initialGap_rank_std + ideologyabs + gender", 
                data = u.mediation.rank)
out.utherm <- lm("actualinf_therm_std ~ perc_inf_num + political_knowledge_std + initialGap_therm_abs_std + ideologyabs + gender", 
                data = u.mediation.therm)


medmod.dapp <- mediation::mediate(
  med.dapp, out.dapp, 
  treat = "political_knowledge_std", mediator = "perc_inf_num",
  cluster = d.mediation.app$chatID
  )
medmod.dsurvey <- mediation::mediate(
  med.dsurvey, out.dsurvey, 
  treat = "political_knowledge_std", mediator = "perc_inf_num",
  cluster = d.mediation.survey$chatID)
medmod.urank <- mediation::mediate(
  med.urank, out.urank, 
  treat = "political_knowledge_std", mediator = "perc_inf_num",
  cluster = u.mediation.rank$chatID)
medmod.utherm <- mediation::mediate(
  med.utherm, out.utherm, 
  treat = "political_knowledge_std", mediator = "perc_inf_num",
  cluster = u.mediation.therm$chatID)

coefs.med <- mutate(tidy(medmod.dapp, conf.int = TRUE), source = "dapp") |> 
  full_join(mutate(tidy(medmod.dsurvey, conf.int = TRUE), source = "dsurvey")) |> 
  full_join(mutate(tidy(medmod.urank, conf.int = TRUE), source = "urank")) |> 
  full_join(mutate(tidy(medmod.utherm, conf.int = TRUE), source = "utherm")) |> 
  mutate(across(where(is.numeric), round, digits = 9)) |> 
  mutate(efftype = ifelse(str_detect(term, "acme"), "Mediation effect", "Direct effect")) |> 
  select(-term) |> 
  distinct()

ggplot(coefs.med, 
       aes(x = estimate, xmin = conf.low, xmax = conf.high, y = efftype, color = source, shape = source)) + 
  geom_pointrange(position = position_dodge(width = .4)) + 
  geom_vline(xintercept = 0) + 
  scale_color_manual(
    breaks = c(
      "dsurvey", 
      "dapp",
      "urank", 
      "utherm"
    ),
    values = c(
      "dsurvey" = "dodgerblue3", 
      "dapp" = "lightskyblue", 
      "urank" = "firebrick3", 
      "utherm" = "palevioletred1"),
    labels = c(
      "DiscussIt: Surveys",
      "DiscussIt: App",
      "UniteDem: Rank", 
      "UniteDem: Thermometer"
    )) +
  scale_shape_manual(
    breaks = c(
      "dsurvey", 
      "dapp",
      "urank", 
      "utherm"
    ),
    values = c(
      "dsurvey" = 17, 
      "dapp" = 17, 
      "urank" = 19, 
      "utherm" = 19),
    labels = c(
      "DiscussIt: Surveys",
      "DiscussIt: App",
      "UniteDem: Rank", 
      "UniteDem: Thermometer"
    )) + 
  labs(x = "Estimated effect of political knowledge on influence",
       y = "",
       color = "Influence measurement",
       shape = "Influence measurement") + 
  theme(text = element_text(family = "serif", size = 12))

ggsave("figs_submit/f4_medplot.png", width = 6, height = 2.5)

```

# Appendix

## Table S1: study sample descriptive statistics

```{r, message = FALSE, warning = FALSE, eval = FALSE}
# loads publicly available data from the 2019 American Community Survey (not included in replication materials) for the purpose of evaluating the composition of the study samples. People from Puerto Rico, noncitizens, and people under 18 years of age are excluded. 
acs <- read_csv("../acs.csv")
```

```{r}
# national stats comparison
study_sumstat <- function(data, var, dataset){
  v <- enquo(var)
  
  d <- data %>%
    filter(!is.na(!!v))
  
  full_num <- nrow(d)
  
  dat_full <- d %>%
    group_by(!!v) %>%
    summarize(full_ntrue = n(),
              full_nsample = full_num,
              full_prop = full_ntrue/full_nsample)
  
  sumstats <- dat_full
  head(dat_full)
  frontcol <- tibble(var_study = rep('none', nrow(dat_full)))
  for(i in 1:nrow(dat_full)){
    frontcol$var_study[i] <- paste0(rlang::as_name(v), ': ', dat_full[i,1])
  }
  
  sumstats <- sumstats[,-1]
  
  toreturn <- cbind(frontcol, sumstats) %>% 
    dplyr::rename("var_{dataset}" := var_study,
                  "{dataset}_ntrue" := full_ntrue,
                  "{dataset}_nsample" := full_nsample,
                  "{dataset}_prop" := full_prop)
  
  return(toreturn)
}
```

```{r}
discussit_demog <- discussit %>% 
  dplyr::select(gender, age, educ, race, party) %>% 
  mutate(gender = as.character(gender),
         age = as.character(age),
         educ = as.character(educ),
         race = as.character(race),
         party = as.character(party)
  )

discussit_age <- study_sumstat(discussit_demog, age, "discussit")
discussit_gender <- study_sumstat(discussit_demog, gender, "discussit")
discussit_educ <- study_sumstat(discussit_demog, educ, "discussit")
discussit_race <- study_sumstat(discussit_demog, race, "discussit")
discussit_party <- study_sumstat(discussit_demog, party, "discussit")

unitedem_demog <- unitedem %>% 
  dplyr::select(gender, age, educ, race) %>% 
  mutate(gender = as.character(gender),
         age = as.character(age),
         educ = as.character(educ),
         race = as.character(race), 
         party = "Democrat")

unitedem_age <- study_sumstat(unitedem_demog, age, "unitedem")
unitedem_gender <- study_sumstat(unitedem_demog, gender, "unitedem")
unitedem_educ <- study_sumstat(unitedem_demog, educ, "unitedem")
unitedem_race <- study_sumstat(unitedem_demog, race, "unitedem")
unitedem_party <- study_sumstat(unitedem_demog, party, "unitedem")
```

```{r, eval = FALSE}
acs_mean_cat <- function(data, ...){
  totalnum <- sum(data$PWGTP)
  totalrows <- nrow(data)
  
  d <- data %>%
    group_by(...) %>%
    summarize(weighted_mean = sum(PWGTP)/totalnum)
  
  frontcol <- tibble(var = rep('none', nrow(d)))
  for(i in 1:nrow(d)){
    frontcol$var[i] <- paste0(colnames(d)[1], ': ', as.character(d[i,1]))
  }
  
  return(cbind(frontcol, d$weighted_mean))
}

acs_educ_mod <- acs %>% 
  mutate(ba = case_when(
    SCHL <= 20 ~ 0, # 2 year degree or less
    SCHL >= 21 ~ 1, # 4 year degree or more
    TRUE ~ NA_real_
  ))

acs_age_mod <- acs %>% 
  mutate(age = case_when(
    AGEP > 17 & AGEP < 40 ~ "young", 
    AGEP >= 40 & AGEP < 60 ~ "middle", 
    AGEP >= 60 ~ "older"
  ))

acs_race_mod <- acs %>% 
  mutate(
    hisp = ifelse(HISP == 1, "Not Hispanic or Latina/Latino", "Hispanic or Latina/Latino"),
    race = dplyr::case_when(
      hisp == "Hispanic or Latina/Latino" ~ "Hispanic or Latina/Latino",
      RAC1P == 1 ~ "White or Caucasian",
      RAC1P == 2 ~ "Black or African American",
      RAC1P %in% c(3, 4, 5, 6, 7, 8, 9) ~ "Other or multiracial",
      TRUE ~ NA_character_)
  )

# create weighted counts: categorical variables
acs_sex <- acs_mean_cat(acs, SEX)
acs_educ <- acs_mean_cat(acs_educ_mod, ba)
acs_age <- acs_mean_cat(acs_age_mod, age)
acs_race <- acs_mean_cat(acs_race_mod, race)

```

```{r, eval = FALSE}
acs_summary <- rbind(acs_sex, acs_age, acs_educ, acs_race) %>% 
  mutate(var = case_when(var == "SEX: 1" ~ "gender: Man",
                          var == "SEX: 2" ~ "gender: Woman",
                          var == "ba: 0" ~ "educ: No BA",
                          var == "ba: 1" ~ "educ: BA",
                          var == "race: Black or African American" ~ "race: Black",
                          var == "race: Hispanic or Latina/Latino" ~ "race: Hispanic",
                          var == "race: Other or multiracial" ~ "race: Other POC or multiracial",
                          var == "race: White or Caucasian" ~ "race: White",
                          TRUE ~ var
))

discussit_summary <- rbind(discussit_gender, discussit_age, discussit_educ, discussit_race, discussit_party)
unitedem_summary <- rbind(unitedem_gender, unitedem_age, unitedem_educ, unitedem_race, unitedem_party)

table_cat <- full_join(acs_summary, discussit_summary, by = c("var" = "var_discussit")) %>% 
  full_join(unitedem_summary, by = c("var" = "var_unitedem")) %>% 
  rename(acs_mean = 'd$weighted_mean')
table_cat$p_discussit <- NA
table_cat$p_unitedem <- NA
```

```{r, eval = FALSE}
table_cat[nrow(table_cat) + 1, 'discussit_prop' ] <- table_cat[1, 'discussit_nsample']
table_cat[nrow(table_cat), 'unitedem_prop' ] <- table_cat[1, 'unitedem_nsample']

table_disp <- table_cat %>% 
  filter(!(var %in% c("gender: Woman", "educ: No BA"))) %>%
    dplyr::select(var, discussit_prop, unitedem_prop, acs_mean, p_discussit, p_unitedem) %>% 
  mutate(var = c(
    "Man",
    "Age 40-59",
    "Age 60+",
    "Age 18-39",
    "Has 4-year degree",
    "Black",
    "Hispanic or Latina/o",
    "Other race or multiracial",
    "White",
    "Democrat",
    "Republican",
    "Study N"
  )) %>% 
  mutate(var = factor(var,
                      levels = c(
                        "Man",
                        "Black",
                        "Hispanic or Latina/o",
                        "White",
                        "Other race or multiracial",
                        "Age 18-39",
                        "Age 40-59",
                        "Age 60+",
                        "Has 4-year degree",
                        "Democrat", 
                        "Republican", 
                        "Study N"
                      ))) %>% 
  dplyr::select(var, everything()) %>% 
  arrange(var) %>% 
  mutate(across(discussit_prop:p_unitedem, ~ round(.x, digits = 2)),
         unitedem_prop = ifelse(is.na(unitedem_prop), 0, unitedem_prop),
         across(-"var", ~ sprintf("%.2f", .x)),
         acs_mean = ifelse(acs_mean == "NA", "", acs_mean)) %>% 
  select(-starts_with("p_"))

table_disp[table_disp$var == "Study N", "discussit_prop"] <- sprintf("%.3s", table_disp[table_disp$var == "Study N", "discussit_prop"])
table_disp[table_disp$var == "Study N", "unitedem_prop"] <- sprintf("%.3s", table_disp[table_disp$var == "Study N", "unitedem_prop"])
table_disp[table_disp$var == "Republican", "unitedem_prop"] <- sprintf("%.1s", table_disp[table_disp$var == "Republican", "unitedem_prop"])

```

```{r, eval = FALSE}
table_disp %>% 
  kable(col.names = c('Variable', 
                    'DiscussIt proportion',
                    'UniteDem proportion',
                    'National proportion (ACS)'
                    ),
      booktabs = T,
      linesep = c('\\addlinespace', '', '', '', '\\addlinespace', '', '','\\addlinespace','\\addlinespace', '','','','\\addlinespace'),
      align = c('l', 'c', 'c', 'c')
      ) %>% 
  column_spec(column = 1, width = "7cm") %>% 
  column_spec(column = 2:4, width = "3cm") |>  
  save_kable("figs_submit/st1_demographics.html")
```

## Political knowledge

### Table S2: political knowledge questions and descriptive statistics

```{r}
discussit_resp_know <- discussit %>% 
  select(starts_with("know")) %>% 
  pivot_longer(cols = everything(), 
               names_to = "question",
               values_to = "response",
               names_prefix = "know_") %>% 
  group_by(question) %>% 
  mutate(n_question = n()) %>% 
  group_by(question, response) %>% 
  summarize(prop = n()/mean(n_question)) %>% 
  distinct() %>% 
  mutate(
    dataset = "DiscussIt",
    response = case_when(response == 0 ~ "incorrect",
                         response == 1 ~ "correct", 
                         is.na(response) ~ "dk_skip"),
    prop = round(prop, digits = 3)) %>% 
  pivot_wider(names_from = "response", values_from = "prop") %>% 
  select(question, correct, incorrect, everything())

unitedem_resp_know <- unitedem %>% 
  select(starts_with("know")) %>% 
  pivot_longer(cols = everything(), 
               names_to = "question",
               values_to = "response",
               names_prefix = "know_") %>% 
  group_by(question) %>% 
  mutate(n_question = n()) %>% 
  group_by(question, response) %>% 
  summarize(prop = n()/mean(n_question)) %>% 
  distinct() %>% 
  mutate(
    dataset = "UniteDem",
         response = case_when(response == 0 ~ "incorrect",
                              response == 1 ~ "correct", 
                              is.na(response) ~ "dk_skip"),
         prop = round(prop, digits = 3)) %>% 
  pivot_wider(names_from = "response", values_from = "prop") %>% 
  select(question, correct, incorrect, everything())

sum_na_questionlevel <- rbind(discussit_resp_know, unitedem_resp_know) %>% 
  pivot_wider(names_from = dataset, values_from = c(correct, incorrect, dk_skip)) %>% 
  mutate(question = factor(question, 
                           levels = c("senator", "speaker", "roberts", "supremeCourt", "majority", "womenInCongress"))) %>% 
  arrange(question) %>% 
  select(question, correct_DiscussIt, incorrect_DiscussIt, dk_skip_DiscussIt, correct_UniteDem, incorrect_UniteDem, dk_skip_UniteDem)

questions_long <- c(
  "How long is the term of office for a U.S. senator?",
  "Who is the current speaker of the U.S. House of Representatives?",
  "What job or office is currently held by John Roberts?",
  "Of the nine members currently serving on the U.S. Supreme Court, how many are women?",
  "Which party holds a majority of seats in the U.S. House of Representatives?",
  "Taking your best guess, what percentage of the U.S. Congress do you think are women?"
)

answers = c(
  "6 years, 2 years, 4 years, 8 years, don't know",
  "Nancy Pelosi, Paul Ryan, Marco Rubio, Harry Reid (DiscussIt only), don't know",
  "Chief Justice of the Supreme Court, Chair of the Democratic National Committee, Senate Majority Leader, Chair of the Republican National Committee, don't know",
  "3, 1, 2, 4, 5, don't know",
  "Democrats, Republicans, don't know",
  "24%, 5%, 46%, 61%"
  )

sum_na_questionlevel[,"questiontext"] <- questions_long
sum_na_questionlevel[,"answers"] <- answers

sum_na_questionlevel <- sum_na_questionlevel %>% 
  select(question, questiontext, answers, everything()) %>% 
  ungroup() %>% 
  select(-"question") %>% 
  mutate(across(where(is.numeric), ~as.character(.))) %>% 
  mutate(across(everything(), ~replace_na(., " ")))

kableExtra::kable(sum_na_questionlevel,
                  col.names = c("Question", "Answer options (correct first)",
                                "Correct", "Incorrect", "Don't know or skip",
                                "Correct", "Incorrect", "Don't know or skip")) %>% 
  kableExtra::add_header_above(c(" " = 2, "DiscussIt" = 3, "UniteDem" = 3)) %>% 
  kableExtra::kable_styling(font_size = 10) |> 
  save_kable("figs_submit/st2_knowledgequestions.html")
```  

### Figure S1: political knowledge histograms

```{r}
totalndiscussit = nrow(discussit)
totalnunitedem = nrow(unitedem)

discussit_know <- discussit %>% 
  select(starts_with("know_")) %>% 
  mutate(anyNA_discussit = is.na(know_speaker) | is.na(know_senator) | is.na(know_roberts),
         total = ifelse(anyNA_discussit, "NA", as.character(know_speaker + know_senator + know_roberts)))%>% 
  group_by(total) %>% 
  summarize(n = n(),
            p = n()/totalndiscussit,
            study = "DiscussIt")

unitedem_know <- unitedem %>% 
  select(starts_with("know")) %>% 
  mutate(anyNA_unitedem = ifelse(rowSums(across(everything(), ~is.na(.x))) > 0, TRUE, FALSE),
         total = ifelse(anyNA_unitedem, "NA", rowSums(across(starts_with("know_"))))) %>% 
  group_by(total) %>% 
  summarize(n = n(),
            p = n()/totalnunitedem,
            study = "UniteDem")

sum_na <- full_join(discussit_know, unitedem_know) %>% 
  full_join(tibble(total = c("0", "2"), n = 0, p = 0, study = "UniteDem")) %>% 
  mutate(total = ifelse(total == "NA", "At least\n1 missing", total)) %>% 
  mutate(total = factor(total, levels = c("At least\n1 missing", "0", "1", "2", "3", "4", "5", "6")))

ggplot(sum_na, aes(x = total, y = p, fill = study)) + 
  geom_col(width = .9) + 
  facet_wrap(facets = "study",
             scales = "free_x") + 
  theme_minimal() + 
  labs(x = "Total knowledge, pre-correction",
       y = "") + 
  theme(legend.position = "none",
        text = element_text(size = 12, family = "serif"))

ggsave("figs_submit/sf1_knowledge_histogram_apdx.png", width = 6, height = 3)
```

### Other don't know/skip corrections

Re-run models (knowledge on perceived and actual influence) for list-wise deletion, incorrect, and correct, in addition to the random assignment. 

```{r}
u_drop <- random_knowledge_unitedem(unitedem, type = "drop")
d_drop <- random_knowledge_discussit(discussit, type = "drop")
u_right <- random_knowledge_unitedem(unitedem, type = "right")
d_right <- random_knowledge_discussit(discussit, type = "right")
u_wrong <- random_knowledge_unitedem(unitedem, type = "wrong")
d_wrong <- random_knowledge_discussit(discussit, type = "wrong")
```

#### Figure S2: effects of political knowledge on influence for different methods of political knowledge imputation

```{r}
inf.dapp.drop <- mod.robust(eq = "actualinf_app_std ~ political_knowledge_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_drop, source = "dapp", knowmis = "drop")
minf.dapp.drop <- inf.dapp.drop[[1]]
coefs.inf.dapp.drop <- inf.dapp.drop[[2]]

inf.dsurvey.drop <- mod.robust("actualinf_survey_std ~ political_knowledge_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_drop, source = "dsurvey", knowmis = "drop")
minf.dsurvey.drop <- inf.dsurvey.drop[[1]]
coefs.inf.dsurvey.drop <- inf.dsurvey.drop[[2]]

inf.urank.drop <- mod.robust(eq = "actualinf_rank_std ~ political_knowledge_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition", data = u_drop, source = "urank", knowmis = "drop")
minf.urank.drop <- inf.urank.drop[[1]]
coefs.inf.urank.drop <- inf.urank.drop[[2]]

inf.utherm.drop <- mod.robust(eq = "actualinf_therm_std ~ political_knowledge_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition", data = u_drop, source = "utherm", knowmis = "drop")
minf.utherm.drop <- inf.utherm.drop[[1]]
coefs.inf.utherm.drop <- inf.utherm.drop[[2]]

inf.dapp.right <- mod.robust(eq = "actualinf_app_std ~ political_knowledge_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_right, source = "dapp", knowmis = "right")
minf.dapp.right <- inf.dapp.right[[1]]
coefs.inf.dapp.right <- inf.dapp.right[[2]]

inf.dsurvey.right <- mod.robust("actualinf_survey_std ~ political_knowledge_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_right, source = "dsurvey", knowmis = "right")
minf.dsurvey.right <- inf.dsurvey.right[[1]]
coefs.inf.dsurvey.right <- inf.dsurvey.right[[2]]

inf.urank.right <- mod.robust(eq = "actualinf_rank_std ~ political_knowledge_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition", data = u_right, source = "urank", knowmis = "right")
minf.urank.right <- inf.urank.right[[1]]
coefs.inf.urank.right <- inf.urank.right[[2]]

inf.utherm.right <- mod.robust(eq = "actualinf_therm_std ~ political_knowledge_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition", data = u_right, source = "utherm", knowmis = "right")
minf.utherm.right <- inf.utherm.right[[1]]
coefs.inf.utherm.right <- inf.utherm.right[[2]]

inf.dapp.wrong <- mod.robust(eq = "actualinf_app_std ~ political_knowledge_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_wrong, source = "dapp", knowmis = "wrong")
minf.dapp.wrong <- inf.dapp.wrong[[1]]
coefs.inf.dapp.wrong <- inf.dapp.wrong[[2]]

inf.dsurvey.wrong <- mod.robust("actualinf_survey_std ~ political_knowledge_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition", data = d_wrong, source = "dsurvey", knowmis = "wrong")
minf.dsurvey.wrong <- inf.dsurvey.wrong[[1]]
coefs.inf.dsurvey.wrong <- inf.dsurvey.wrong[[2]]

inf.urank.wrong <- mod.robust(eq = "actualinf_rank_std ~ political_knowledge_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition", data = u_wrong, source = "urank", knowmis = "wrong")
minf.urank.wrong <- inf.urank.wrong[[1]]
coefs.inf.urank.wrong <- inf.urank.wrong[[2]]

inf.utherm.wrong <- mod.robust(eq = "actualinf_therm_std ~ political_knowledge_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition", data = u_wrong, source = "utherm", knowmis = "wrong")
minf.utherm.wrong <- inf.utherm.wrong[[1]]
coefs.inf.utherm.wrong <- inf.utherm.wrong[[2]]

coefs.inf.knowrobust <- coefs.inf.dapp.drop |> 
  full_join(coefs.inf.dsurvey.drop) |> 
  full_join(coefs.inf.urank.drop) |> 
  full_join(coefs.inf.utherm.drop) |> 
  full_join(coefs.inf.dapp.right) |> 
  full_join(coefs.inf.dsurvey.right) |> 
  full_join(coefs.inf.urank.right) |> 
  full_join(coefs.inf.utherm.right) |> 
  full_join(coefs.inf.dapp.wrong) |> 
  full_join(coefs.inf.dsurvey.wrong) |> 
  full_join(coefs.inf.urank.wrong) |> 
  full_join(coefs.inf.utherm.wrong) |> 
  full_join(coefs.inf.dapp) |> 
  full_join(coefs.inf.dsurvey) |> 
  full_join(coefs.inf.urank) |> 
  full_join(coefs.inf.utherm) |> 
  filter(str_detect(term, "knowledge")) |> 
  mutate(knowmis = factor(knowmis, levels = c("wrong", "right", "drop", "randassign")))

ggplot(coefs.inf.knowrobust, aes(y = source, x = estimate, xmin = lower, xmax = upper, color = knowmis)) +
  geom_vline(xintercept = 0, alpha = .5) +
  geom_pointrange(position = position_dodge(width = .3)) + 
  scale_y_discrete(
    breaks = c(
      "dapp",
      "dsurvey",
      "urank",
      "utherm"
    ),
    labels = c(
      "DiscussIt: App",
      "DiscussIt: Survey",
      "UniteDem: Rank",
      "UniteDem: Thermometer"
    )
  ) +
  scale_color_manual(
    breaks = c(
      "randassign",
      "drop",
      "right",
      "wrong"
    ),
    values = c(
      "randassign" = "black",
      "drop" = "blue",
      "right" = "darkgreen",
      "wrong" = "red"),
    labels = c(
      "Random (main text)",
      "Dropped",
      "Correct",
      "Incorrect"
    )) +
  labs(y = "",
       x = "Estimated effect of political knowledge on influence",
       color = "Knowledge correction") + 
  theme(text = element_text(size = 12, family = "serif"))

ggsave("figs_submit/sf2_infeffects_knowrobust.png", width = 6, height = 3)
```

#### Figure S3: coefficients of perceived influence models for different methods of political knowledge imputation

```{r}
percinf.dapp.drop <- mod.robust(eq = "perc_inf ~ political_knowledge_std + actualinf_app_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_drop, source = "dapp", knowmis = "drop", fam = "ord")
mpercinf.dapp.drop <- percinf.dapp.drop[[1]]
coefs.percinf.dapp.drop <- percinf.dapp.drop[[2]]

percinf.dsurvey.drop <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_survey_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_drop, source = "dsurvey", knowmis = "drop", fam = "ord")
mpercinf.dsurvey.drop <- percinf.dsurvey.drop[[1]]
coefs.percinf.dsurvey.drop <- percinf.dsurvey.drop[[2]]

percinf.urank.drop <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_rank_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition",
                      data = u_drop, source = "urank", knowmis = "drop", fam = "ord")
mpercinf.urank.drop <- percinf.urank.drop[[1]]
coefs.percinf.urank.drop <- percinf.urank.drop[[2]]

percinf.utherm.drop <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_therm_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition",
                      data = u_drop, source = "utherm", knowmis = "drop", fam = "ord")
mpercinf.utherm.drop <- percinf.utherm.drop[[1]]
coefs.percinf.utherm.drop <- percinf.utherm.drop[[2]]



percinf.dapp.right <- mod.robust(eq = "perc_inf ~ political_knowledge_std + actualinf_app_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_right, source = "dapp", knowmis = "right", fam = "ord")
mpercinf.dapp.right <- percinf.dapp.right[[1]]
coefs.percinf.dapp.right <- percinf.dapp.right[[2]]

percinf.dsurvey.right <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_survey_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_right, source = "dsurvey", knowmis = "right", fam = "ord")
mpercinf.dsurvey.right <- percinf.dsurvey.right[[1]]
coefs.percinf.dsurvey.right <- percinf.dsurvey.right[[2]]

percinf.urank.right <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_rank_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition",
                      data = u_right, source = "urank", knowmis = "right", fam = "ord")
mpercinf.urank.right <- percinf.urank.right[[1]]
coefs.percinf.urank.right <- percinf.urank.right[[2]]

percinf.utherm.right <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_therm_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition",
                      data = u_right, source = "utherm", knowmis = "right", fam = "ord")
mpercinf.utherm.right <- percinf.utherm.right[[1]]
coefs.percinf.utherm.right <- percinf.utherm.right[[2]]



percinf.dapp.wrong <- mod.robust(eq = "perc_inf ~ political_knowledge_std + actualinf_app_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_wrong, source = "dapp", knowmis = "wrong", fam = "ord")
mpercinf.dapp.wrong <- percinf.dapp.wrong[[1]]
coefs.percinf.dapp.wrong <- percinf.dapp.wrong[[2]]

percinf.dsurvey.wrong <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_survey_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_wrong, source = "dsurvey", knowmis = "wrong", fam = "ord")
mpercinf.dsurvey.wrong <- percinf.dsurvey.wrong[[1]]
coefs.percinf.dsurvey.wrong <- percinf.dsurvey.wrong[[2]]

percinf.urank.wrong <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_rank_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition",
                      data = u_wrong, source = "urank", knowmis = "wrong", fam = "ord")
mpercinf.urank.wrong <- percinf.urank.wrong[[1]]
coefs.percinf.urank.wrong <- percinf.urank.wrong[[2]]

percinf.utherm.wrong <- mod.robust("perc_inf ~ political_knowledge_std + actualinf_therm_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition",
                      data = u_wrong, source = "utherm", knowmis = "wrong", fam = "ord")
mpercinf.utherm.wrong <- percinf.utherm.wrong[[1]]
coefs.percinf.utherm.wrong <- percinf.utherm.wrong[[2]]



coefs.percinf.knowrobust <- coefs.percinf.dapp |>
  full_join(coefs.percinf.dsurvey) |>
  full_join(coefs.percinf.urank) |>
  full_join(coefs.percinf.utherm) |>
  full_join(coefs.percinf.dapp.drop) |> 
  full_join(coefs.percinf.dsurvey.drop) |> 
  full_join(coefs.percinf.urank.drop) |> 
  full_join(coefs.percinf.utherm.drop) |> 
  full_join(coefs.percinf.dapp.right) |> 
  full_join(coefs.percinf.dsurvey.right) |> 
  full_join(coefs.percinf.urank.right) |> 
  full_join(coefs.percinf.utherm.right) |> 
  full_join(coefs.percinf.dapp.wrong) |> 
  full_join(coefs.percinf.dsurvey.wrong) |> 
  full_join(coefs.percinf.urank.wrong) |> 
  full_join(coefs.percinf.utherm.wrong) |> 
  filter(str_detect(term, "knowledge|ideology|actualinf|MyRank1")) |>
  mutate(
    data = ifelse(str_detect(source, "^d"), "DiscussIt", "UniteDem"),
    dispterm = case_when(
      str_detect(term, "actualinf|MyRank1") ~ "Influence",
      term == "ideology" ~ "Ideology (linear)",
      term == "ideologyabs" ~ "Ideology (absolute val)",
      # term == "ideology2" ~ "Ideology (squared)",
      term == "political_knowledge_std" ~ "Political knowledge"),
    dispterm = factor(dispterm, levels = c("Influence", "Political knowledge", "Ideology (linear)", "Ideology (squared)", "Ideology (absolute val)"), ordered = TRUE),
    knowmis = factor(knowmis, levels = c("wrong", "right", "drop", "randassign"))
  )

ggplot(coefs.percinf.knowrobust, aes(y = dispterm, x = exp(estimate), xmin = exp(lower), xmax = exp(upper), color = knowmis)) +
  geom_vline(xintercept = 1, alpha = .5) +
  geom_pointrange(position = position_dodge2(width = .5)) +
  scale_color_manual(
    breaks = c(
      "randassign",
      "drop",
      "right",
      "wrong"
    ),
    values = c(
      "randassign" = "black",
      "drop" = "blue",
      "right" = "darkgreen",
      "wrong" = "red"),
    labels = c(
      "Random (main text)",
      "Dropped",
      "Correct",
      "Incorrect"
    )) +
  scale_y_discrete(limits = rev) +
  facet_wrap(facets = "source",
             labeller = as_labeller(c("dapp" = "DiscussIt: App",
                                      "dsurvey" = "DiscussIt: Survey",
                                      "urank" = "UniteDem: Rank", 
                                      "utherm" = "UniteDem: Thermometer"))
             ) +
  labs(y = "",
       x = "Estimated effects on perceived influence\n(exponentiated log odds units)",
       color = "Knowledge correction"
  ) +
  theme(text = element_text(size = 12, family = "serif"),
        legend.position = "bottom") + 
  guides(color = guide_legend(nrow = 2))

ggsave("figs_submit/sf3_percinfeffects_knowrobust.png", width = 6, height = 4)
```

## Table S3: T-test results corresponding to Figure 1

```{r}
percinftab <- ttest_stats |> 
  mutate(
    estimate_FALSE = paste0(round(mean_FALSE, digits = 2), " (", round(sqrt(var_FALSE), digits = 2), ")"),
    estimate_TRUE = paste0(round(mean_TRUE, digits = 2), " (", round(sqrt(var_TRUE), digits = 2), ")"),
    t = round(t, digits = 2),
    p_df = round(p_df, digits = 3),
    name = case_when(
      source == "app" ~ "DiscussIt: App",
      source == "survey" ~ "DiscussIt: Survey",
      source == "rank" ~ "UniteDem: Rank",
      source == "therm" ~ "UniteDem: Thermometer"
    )
  ) |> 
  select(name, estimate_FALSE, n_FALSE, estimate_TRUE, n_TRUE, t, p_df)

names(percinftab) <- c("Study", "Estimate", "N", "Estimate", "N", "t value", "p value")

tinytable::tt(percinftab) |> 
  tinytable::group_tt(j = list(
    "Did not influence partner" = 2:3,
    "Influenced partner" = 4:5
  ))

# names(discussit_plot)
# 
# d_basicstats <- discussit_plot |> 
#   group_by(converge_app) |> 
#   filter(!is.na(perc_inf_num)) |> 
#   summarize(sd_pi = sd(perc_inf_num),
#             mean_pi = mean(perc_inf_num))
# 
# d_basicstats
```

## Main text model coefficient tables

```{r}
rename_tabs <- function(oldnames){
  newnames <- gsub(".*Gap.*", "Initial opinion gap", oldnames)
  newnames <- gsub(".*political_knowledge_std:displayConditionincorrect", "Pol. knowledge*incorrect labels", newnames)
  newnames <- gsub(".*political_knowledge_std:displayConditioncorrect", "Pol. knowledge*correct labels", newnames)
  newnames <- gsub(".*political_knowledge_std:topicgunControl", "Pol. knowledge*gun control", newnames)
  newnames <- gsub(".*political_knowledge_std:manipulationConditionopposite_partnermislabel", "Pol. knowledge*other, partner mislabeled", newnames)
  newnames <- gsub(".*political_knowledge_std:manipulationConditionopposite_selfmislabel", "Pol. knowledge*other, self mislabeled", newnames)
  newnames <- gsub(".*political_knowledge_std:manipulationConditionsame_none", "Pol. knowledge*same, correct labels", newnames)
  newnames <- gsub(".*political_knowledge_std:manipulationConditionopposite_none", "Pol. knowledge*other, correct labels", newnames)
  newnames <- gsub(".*political_knowledge_std.*", "Political knowledge", newnames)
  newnames <- gsub("^ideology$", "Ideology (linear)", newnames)
  newnames <- gsub("^ideologyabs$", "Ideology (absolute val)", newnames)
  # newnames <- gsub("^ideology2$", "Ideology (squared)", newnames)
  newnames <- gsub(".*Man$", "Man (ref: woman)", newnames)
  newnames <- gsub(".*Republican$", "Republican (ref: Democrat)", newnames)
  newnames <- gsub(".*gunControl", "Topic: gun control (ref: immigration)", newnames)
  newnames <- gsub(".*incorrect$", "Incorrect labels", newnames)
  newnames <- gsub("^displayConditioncorrect$", "Correct labels", newnames)
  newnames <- gsub("^manipulationConditionopposite_partnermislabel$", "Other gender, partner mislabeled", newnames)
  newnames <- gsub("^manipulationConditionopposite_selfmislabel$", "Other gender, self mislabeled", newnames)
  newnames <- gsub("^manipulationConditionsame_none$", "Same gender, correct labels", newnames)
  newnames <- gsub("^manipulationConditionopposite_none$", "Other gender, correct labels", newnames)
  newnames <- gsub("^actual.*", "Influence", newnames)
  newnames <- gsub(".*MyRank1Pre.*", "Influence", newnames)
  newnames <- gsub("Disagree very strongly", "Dsag v str", newnames)
  newnames <- gsub("Disagree strongly", "Dsag str", newnames)
  newnames <- gsub("Disagree somewhat", "Dsag smwht", newnames)
  newnames <- gsub("Neither agree nor disagree", "Neither", newnames)
  newnames <- gsub("Agree very strongly", "Agr v str", newnames)
  newnames <- gsub("Agree strongly", "Agr str", newnames)
  newnames <- gsub("Agree somewhat", "Agr smwht", newnames)
  setNames(newnames, oldnames)
}
```


### Table S4: perceived influence coefficients

```{r}
percinftab <- modelsummary::modelsummary(
  models = list(
    "DiscussIt: App" = mpercinf.dapp, 
    "DiscussIt: Surveys" = mpercinf.dsurvey, 
    "UniteDem: Rank" = mpercinf.urank, 
    "UniteDem: Thermometer" = mpercinf.utherm),
  estimate = "{estimate} (p={p.value})",
  statistic = c("conf.int"),
  conf.level = .95,
  vcov = ~chatID,
  coef_rename = rename_tabs,
  # output = "html", 
  gof_omit = "Std.Errors|AIC|BIC|Log.Lik|RMSE",
  exponentiate = TRUE,
  output = "kableExtra"
  ) |> 
  pack_rows(group_label = "Intercepts", start_row = 1, end_row = 12) |> 
  pack_rows(group_label = "Partisan labeling (ref: no partisan labels)", start_row = 29, end_row = 32) |> 
  pack_rows(group_label = "Gender labeling (ref: other gender conversation, correct gender labels)", start_row = 33, end_row = 38) |> 
  column_spec(1, bold = TRUE) |> 
  save_kable("figs_submit/st4_percinftable.html")
```

### Table S5: influence coefficients

```{r}
inftab <- modelsummary::modelsummary(
  models = list(
    "DiscussIt: App" = minf.dapp, 
    "DiscussIt: Surveys" = minf.dsurvey, 
    "UniteDem: Rank" = minf.urank, 
    "UniteDem: Thermometer" = minf.utherm),
  estimate = "{estimate} (p={p.value})",
  statistic = c("conf.int"),
  conf.level = .95,
  vcov = ~chatID,
  coef_rename = rename_tabs,
  # output = "html", 
  gof_omit = "Std.Errors|AIC|BIC|Log.Lik|RMSE",
  output = "kableExtra"
  ) |> 
  pack_rows(group_label = "Partisan labeling (ref: no partisan labels)", start_row = 17, end_row = 20) |> 
  pack_rows(group_label = "Gender labeling (ref: other gender conversation, correct gender labels)", start_row = 21, end_row = 26) |> 
  column_spec(1, bold = TRUE) |>
  save_kable("figs_submit/st5_inftable.html")
```

## Interaction effects between political knowledge and experimental conditions

```{r}
percinf.dapp.interact <- mod.robust(eq = "perc_inf ~ political_knowledge_std*displayCondition + political_knowledge_std*topic + actualinf_app_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_randassign, source = "dapp", knowmis = "randassign", fam = "ord")
mpercinf.dapp.interact <- percinf.dapp.interact[[1]]
coefs.percinf.dapp.interact <- percinf.dapp.interact[[2]]

percinf.dsurvey.interact <- mod.robust(eq = "perc_inf ~ political_knowledge_std*displayCondition + political_knowledge_std*topic + actualinf_survey_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_randassign, source = "dsurvey", knowmis = "randassign", fam = "ord")
mpercinf.dsurvey.interact <- percinf.dsurvey.interact[[1]]
coefs.percinf.dsurvey.interact <- percinf.dsurvey.interact[[2]]

percinf.dapp.interact.disp <- mod.robust(eq = "perc_inf ~ political_knowledge_std*displayCondition + actualinf_app_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_randassign, source = "dapp", knowmis = "randassign", fam = "ord")
mpercinf.dapp.interact.disp <- percinf.dapp.interact.disp[[1]]

percinf.dsurvey.interact.disp <- mod.robust(eq = "perc_inf ~ political_knowledge_std*displayCondition + actualinf_survey_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_randassign, source = "dsurvey", knowmis = "randassign", fam = "ord")
mpercinf.dsurvey.interact.disp <- percinf.dsurvey.interact.disp[[1]]

percinf.dapp.interact.topic <- mod.robust(eq = "perc_inf ~ political_knowledge_std*topic + actualinf_app_std + initialGap_app_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_randassign, source = "dapp", knowmis = "randassign", fam = "ord")
mpercinf.dapp.interact.topic <- percinf.dapp.interact.topic[[1]]

percinf.dsurvey.interact.topic <- mod.robust(eq = "perc_inf ~  political_knowledge_std*topic + actualinf_survey_std + initialGap_survey_abs_std + ideology + ideologyabs + gender + party + topic + displayCondition",
                      data = d_randassign, source = "dsurvey", knowmis = "randassign", fam = "ord")
mpercinf.dsurvey.interact.topic <- percinf.dsurvey.interact.topic[[1]]

percinf.urank.interact <- mod.robust(eq = "perc_inf ~ political_knowledge_std*manipulationCondition + actualinf_rank_std + initialGap_rank_std + ideologyabs + gender + manipulationCondition",
                      data = u_randassign, source = "urank", knowmis = "randassign", fam = "ord")
mpercinf.urank.interact <- percinf.urank.interact[[1]]
coefs.percinf.urank.interact <- percinf.urank.interact[[2]]

percinf.utherm.interact <- mod.robust(eq = "perc_inf ~ political_knowledge_std*manipulationCondition + actualinf_therm_std + initialGap_therm_abs_std + ideologyabs + gender + manipulationCondition",
                      data = u_randassign, source = "utherm", knowmis = "randassign", fam = "ord")
mpercinf.utherm.interact <- percinf.utherm.interact[[1]]
coefs.percinf.utherm.interact <- percinf.utherm.interact[[2]]
```

### Table S6: DiscussIt experiment interaction coefficients

```{r}
d_interacttab <- modelsummary::modelsummary(
  models = list(
    "DiscussIt: App" = mpercinf.dapp.interact, 
    "DiscussIt: Surveys" = mpercinf.dsurvey.interact), 
  estimate = "{estimate} (p={p.value})",
  statistic = c("conf.int"),
  conf.level = .95,
  vcov = ~chatID,
  coef_rename = rename_tabs,
  # output = "html", 
  gof_omit = "Std.Errors|AIC|BIC|Log.Lik|RMSE",
  exponentiate = TRUE,
  output = "kableExtra"
  ) |>
  pack_rows(group_label = "Intercepts", start_row = 1, end_row = 12) |>
  pack_rows(group_label = "Partisan labeling (ref: no partisan labels)", start_row = 15, end_row = 18) |>
  pack_rows(group_label = "Political knowledge*DiscussIt experimental conditions", start_row = 33, end_row = 38) |>
  column_spec(1, bold = TRUE) |>
  save_kable("figs_submit/st6_discussitinteractiontable.html")
```

### Table S7: UniteDem experiment interaction coefficients

```{r}
u_interacttab <- modelsummary::modelsummary(
  models = list(
    "UniteDem: Rank" = mpercinf.urank.interact, 
    "UniteDem: Thermometer" = mpercinf.utherm.interact),
  estimate = "{estimate} (p={p.value})",
  statistic = c("conf.int"),
  conf.level = .95,
  vcov = ~chatID,
  coef_rename = rename_tabs,
  # output = "html", 
  gof_omit = "Std.Errors|AIC|BIC|Log.Lik|RMSE",
  exponentiate = TRUE,
  output = "kableExtra"
  ) |> 
  pack_rows(group_label = "Intercepts", start_row = 1, end_row = 12) |>
  pack_rows(group_label = "Gender labeling (ref: other gender conversation, correct gender labels)", start_row = 15, end_row = 20) |>
pack_rows(group_label = "Political knowledge*UniteDem experimental conditions", start_row = 29, end_row = 34) |>
  column_spec(1, bold = TRUE) |>
  save_kable("figs_submit/st7_unitedeminteractiontable.html")
```

### Figure S4: predicted values plot

```{r}
nd_unitedem <- tibble(
  political_knowledge_std = rep(
    seq(min(u_randassign$political_knowledge_std), max(u_randassign$political_knowledge_std), 
        length.out = length(unique(u_randassign$political_knowledge_std))), 
    4), 
  manipulationCondition = c(
    rep("opposite_none", length(unique(u_randassign$political_knowledge_std))), 
    rep("opposite_partnermislabel", length(unique(u_randassign$political_knowledge_std))),
    rep("opposite_selfmislabel", length(unique(u_randassign$political_knowledge_std))),
    rep("same_none", length(unique(u_randassign$political_knowledge_std)))
  ), 
  actualinf_rank_std = 0, 
  actualinf_therm_std = 0, 
  initialGap_rank_std = median(u_randassign$initialGap_rank_std),
  initialGap_therm_abs_std = median(u_randassign$initialGap_therm_abs_std),
  ideologyabs = median(u_randassign$ideologyabs, na.rm = TRUE),
  gender = "Woman"
)

nd_discussit_topic <- tibble(
  political_knowledge_std = rep(
    seq(min(d_randassign$political_knowledge_std), max(d_randassign$political_knowledge_std), 
        length.out = length(unique(d_randassign$political_knowledge_std))), 
    2), 
  topic = c(
    rep("gunControl", length(unique(d_randassign$political_knowledge_std))), 
    rep("immigration", length(unique(d_randassign$political_knowledge_std)))
  ), 
  actualinf_survey_std = 0,
  initialGap_survey_abs_std = median(d_randassign$initialGap_survey_abs_std, na.rm = TRUE),
  ideology = median(d_randassign$ideology, na.rm = TRUE),
  ideologyabs = abs(ideology),
  gender = "Woman",
  party = "Democrat", 
  displayCondition = "none"
)

nd_discussit_disp <- tibble(
  political_knowledge_std = rep(
    seq(min(d_randassign$political_knowledge_std), max(d_randassign$political_knowledge_std), 
        length.out = length(unique(d_randassign$political_knowledge_std))), 
    3), 
  displayCondition = c(
    rep("none", length(unique(d_randassign$political_knowledge_std))), 
    rep("correct", length(unique(d_randassign$political_knowledge_std))),
    rep("incorrect", length(unique(d_randassign$political_knowledge_std)))
  ), 
  actualinf_survey_std = 0,
  initialGap_survey_abs_std = median(d_randassign$initialGap_survey_abs_std, na.rm = TRUE),
  ideology = median(d_randassign$ideology, na.rm = TRUE),
  ideologyabs = abs(ideology),
  gender = "Woman",
  party = "Democrat", 
  topic = "immigration"
)

pred_d.survey_topic <- predict(mpercinf.dsurvey.interact, nd_discussit_topic)$fit |> 
  as_tibble() |> 
  cbind(nd_discussit_topic) |> 
  pivot_longer(
    contains("gree"), names_to = "response", values_to = "estimate"
  ) |> 
  mutate(response = factor(response, 
                           levels = levels(d_randassign$perc_inf)))

pred_d.survey_disp <- predict(mpercinf.dsurvey.interact, nd_discussit_disp)$fit |> 
  as_tibble() |> 
  cbind(nd_discussit_disp) |> 
  pivot_longer(
    contains("gree"), names_to = "response", values_to = "estimate"
  ) |> 
  mutate(response = factor(response, 
                           levels = levels(d_randassign$perc_inf)))

pred_u.rank <- predict(mpercinf.urank.interact, nd_unitedem)$fit |> 
  as_tibble() |> 
  cbind(nd_unitedem) |> 
  pivot_longer(
    contains("gree"), names_to = "response", values_to = "estimate"
  ) |> 
  mutate(response = factor(response, 
                           levels = levels(u_randassign$perc_inf)),
         manipulationCondition = factor(manipulationCondition, 
                                         levels = c("opposite_none",
                                                    "opposite_selfmislabel", 
                                                    "opposite_partnermislabel",
                                                    "same_none")),
         homophily = ifelse(manipulationCondition %in% c("opposite_partnermislabel", "same_none"), 
                            "Appears same gender", "Appears other gender"),
         facetcol = ifelse(manipulationCondition %in% c("opposite_none", "opposite_partnermislabel"), 
                      "1", "2"))

colors <- brewer.pal(7, 'PuOr')
names(colors) <- levels(u_randassign$perc_inf)
custom_fill <- scale_fill_manual(name = "I influenced my partner", values = colors)
custom_color <- scale_color_manual(name = "I influenced my partner", values = colors)


facetlabs_d_topic <- c("Gun control", "Immigration")
names(facetlabs_d_topic) <- c("gunControl", "immigration")
facetlabs_d_disp <- c(
  none = "None",
  correct = "Correct",
  incorrect = "Incorrect"
)


facetlabs_u <- c(
  `opposite_none` = "Other gender\ncorrect labels",
  `same_none` = "Same gender\ncorrect labels",
  `opposite_selfmislabel` = "Other gender\nself mislabeled",
  `opposite_partnermislabel` = "Other gender\nprtnr mislabeled"
)

# Make barplots
u.barplot <- ggplot(data = pred_u.rank, aes(x = factor(political_knowledge_std), y = estimate, color = response, fill = response)) + 
  geom_bar(stat = "identity", position = "stack", width = .8) + 
  custom_color + 
  custom_fill + 
  facet_wrap(
    facets = "manipulationCondition",
    labeller = as_labeller(facetlabs_u)) + 
  theme_minimal() + 
  labs(y = "",
       x = "Political knowledge") +
  scale_x_discrete(labels = sort(as.numeric(unique(u_randassign$political_knowledge))))  + 
  scale_y_continuous(
    "",
    sec.axis = sec_axis(~ ., name = "Partner appears                        Partner appears\nother-gender                            same gender", breaks = NULL)) + 
  theme(text = element_text(size = 12, family = "serif"),
        axis.title.y.right = element_text(size = 10),
        legend.position = "none") + 
  labs(title = "UniteDem",
       subtitle = "Gender composition and labeling")

d.barplot.topic <- ggplot(data = pred_d.survey_topic, aes(x = factor(political_knowledge_std), y = estimate, color = response, fill = response)) + 
  geom_bar(stat = "identity", position = "stack", width = .8) + 
  custom_color + 
  custom_fill + 
  facet_wrap(facets = "topic",
             labeller = labeller(topic = facetlabs_d_topic)) + 
  theme_minimal() + 
  labs(y = "Estimated response proportion") +
  scale_x_discrete(labels = sort(as.numeric(unique(d_randassign$political_knowledge))))  + 
  theme(text = element_text(size = 12, family = "serif"),
        legend.position = "none",
        axis.title.x = element_blank()) + 
  labs(title = "DiscussIt",
       subtitle = "Discussion topic")

d.barplot.disp <- ggplot(data = pred_d.survey_disp, aes(x = factor(political_knowledge_std), y = estimate, color = response, fill = response)) + 
  geom_bar(stat = "identity", position = "stack", width = .8) + 
  custom_color + 
  custom_fill + 
  facet_wrap(facets = "displayCondition",
             labeller = labeller(displayCondition = facetlabs_d_disp)) + 
  theme_minimal() + 
  labs(y = "Estimated response proportion",
       x = "Political knowledge") +
  scale_x_discrete(labels = sort(as.numeric(unique(d_randassign$political_knowledge))))  + 
  theme(text = element_text(size = 12, family = "serif"),
        legend.position = "bottom") +   
  guides(
    fill = guide_legend(nrow = 4, direction = "vertical"),
    color = guide_legend(nrow = 4, direction = "vertical"),
  ) +
  labs(subtitle = "Partisan labels")

(d.barplot.topic/d.barplot.disp + plot_layout(axes = "collect")) | 
  u.barplot + 
  plot_layout(guides = "collect")

ggsave("figs_submit/sf4_interactionbarplots.png", width = 6, height = 6)
  
```